#include "serial.h"

serial::serial()
{ 
  timeOutEstourado = false;
  msgEnviada = false;
  arduinoResetou = false;
}

serial::~serial()
{ }

// takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1")
// and a baud rate (bps) and connects to that port at that speed and 8N1.
// opens the port in fully raw mode so you can send binary data.
// returns valid fd, or -1 on error
int serial::serialport_init(const char* serialport, int baud)
{
    struct termios toptions;
    int fd;
    
    //fprintf(stderr,"init_serialport: opening port %s @ %d bps\n",
    //        serialport,baud);

    fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)  {
        perror("init_serialport: Unable to open port ");
        return -1;
    }
    
    if (tcgetattr(fd, &toptions) < 0) {
        perror("init_serialport: Couldn't get term attributes");
        return -1;
    }
    speed_t brate = baud; // let you override switch below if needed
    switch(baud) {
    case 4800:   brate=B4800;   break;
    case 9600:   brate=B9600;   break;
// if you want these speeds, uncomment these and set #defines if Linux
//#ifndef OSNAME_LINUX
//    case 14400:  brate=B14400;  break;
//#endif
    case 19200:  brate=B19200;  break;
//#ifndef OSNAME_LINUX
//    case 28800:  brate=B28800;  break;
//#endif
//    case 28800:  brate=B28800;  break;
    case 38400:  brate=B38400;  break;
    case 57600:  brate=B57600;  break;
    case 115200: brate=B115200; break;
    }
    cfsetispeed(&toptions, brate);
    cfsetospeed(&toptions, brate);


    // 8N1
    toptions.c_cflag &= ~PARENB;
    toptions.c_cflag |= CSTOPB;
    toptions.c_cflag &= ~CSIZE;
    toptions.c_cflag |= CS8;
    
    //fcntl(fd, F_SETFL, FNDELAY); // read() retorna imediatamente( n=0 ) se nao tem nada pra ler!!!
    
    // no flow control
 /*   toptions.c_cflag &= ~CRTSCTS;

    toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
    toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl

    toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    toptions.c_oflag &= ~OPOST; // make raw

    // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
    toptions.c_cc[VMIN]  = 0;
    toptions.c_cc[VTIME] = 20;
  */  
    if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
        perror("init_serialport: Couldn't set term attributes");
        return -1;
    }

    return fd;
}

    
int serial::serialport_write(int fd,const char* str)
{
    int len = strlen(str);
    int n = write(fd, (void *)str, len);
    if( n!=len ) 
        return -1;
    return 0;
}

int serial::serialport_read_until(int fd, char* buf, int until)
{
    char b[1];
    int i=0;
    
    do 
    { 
	  int n = read(fd, b, 1);  // read a char at a time
	  
	  if( n==-1) 
	    return -1;    // couldn't read
	    
	  if( (n==0) ) 
	  {
	      if( !timeOutEstourado && (msgEnviada==true) ) // se msgEnviada=0 -> thread checando serial
	      {
		usleep( 10 * 1000 ); // wait 10 msec try again
		continue;
	      }
	      else
		return -1; // timeOut estourou, retransmitir...
	  }
	  buf[i] = b[0]; i++;
	  
    }while( b[0] != until );
 
    buf[i] = 0;  // null terminate the string
    return i;
}

